package com.pisolution.scheduler.runtime.master.dispatcher;

import com.pisolution.scheduler.core.tuple.Tuple3;
import com.pisolution.scheduler.remote.command.Command;
import com.pisolution.scheduler.remote.utils.Host;
import com.pisolution.scheduler.runtime.master.dispatcher.executor.NettyExecutorManager;
import com.pisolution.scheduler.runtime.master.dispatcher.host.HostManager;
import com.pisolution.scheduler.runtime.master.dispatcher.host.RandomHostManager;

import org.springframework.stereotype.Service;

/**
 * 从待运行给定任务的工作节点分组中选择一个适当的工作节点运行给定任务.
 *
 * @author sora
 * @version 0.1.0
 */
@Service
public class ExecutorDispatcher {
    /** 用于发送任务至工作节点. */
    private final NettyExecutorManager manager;

    /** 用于选取执行指令的工作节点. */
    private final HostManager selector;

    // -------------------------------------------------------------------------------------------------
    //  初始化
    // -------------------------------------------------------------------------------------------------

    public ExecutorDispatcher(final NettyExecutorManager manager, final RandomHostManager selector) {
        this.manager = manager;
        this.selector = selector;
    }

    // -------------------------------------------------------------------------------------------------
    //  任务分发
    // -------------------------------------------------------------------------------------------------

    /**
     * 将给定指令发送至工作节点 目标工作节点将依据节点选择算法计算得出.
     *
     * @param context 指令上下文.
     *
     * @return 如果发送成功则返回 {@code true} 否则返回 {@code false}.
     *
     * @throws Exception 如果发送过程中出现问题.
     */
    public boolean dispatch(final Tuple3<Host, Command, String> context) throws Exception {
        // 1. 选取工作节点.
        context.field1 = this.selector.select(context);

        // 2. 尝试发送指令.
        this.manager.beforeExecute(context);

        try {
            return this.manager.execute(context);
        } finally {
            this.manager.afterExecute(context);
        }
    }
}
